﻿using M.Core.RmoteCall.Attributes;
using System;
using System.Collections.Concurrent;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using Thrift.Transports;
using Thrift.Transports.Client;
using System.Linq;
using M.Core.RmoteCall.RpcCall.Pool;

namespace M.Core.RmoteCall.RpcCall
{
    public class RpcServiceInfo: IDisposable
    {
        public RpcServiceInfo(IPEndPoint iPEndPoint)
        {
            this.iPEndPoint = iPEndPoint;

            RpcServiceInfo callModel = this;
        }

        public void InitPool()
        {
            int count = 50;

            var pool = this;
            rpcPool = new RpcPool(40, count, () =>
            {
                CallSocketObject callSocketObject = new CallSocketObject(pool);
                callSocketObject.InitSocket().GetAwaiter().GetResult();
                return callSocketObject;
            });
       
        }
        public IPEndPoint iPEndPoint { get; set; }
        public string Key { get; internal set; }

        private RpcPool rpcPool { get; set; }
        public string Name { get; internal set; }

        public RpcPoolItem GetOneClient()
        {
            var item = rpcPool.GetOne();
            return item;
        }

        public class CallSocketObject
        {
            public RpcServiceInfo callModel { get; set; }
            public CallSocketObject(RpcServiceInfo callModel)
            {
                this.callModel = callModel;
            }



            public TClientTransport trans { get; set; }

            public ConcurrentDictionary<int, CallClientInfo> map = new ConcurrentDictionary<int, CallClientInfo>();

            public async Task InitSocket()
            {
               
                trans = new TSocketClientTransport(callModel.iPEndPoint.Address, callModel.iPEndPoint.Port);
                await trans.OpenAsync();


                //Type t = typeof(AppInfoAttribute);

                //var alla = AppDomain.CurrentDomain.GetAssemblies();
                //foreach (var item in alla)
                //{
                //    var attrs = item.GetTypes().Where(i => i.GetCustomAttributes(t, false).Any());
                //    foreach (var sitem in attrs)
                //    {
                //        var a = (AppInfoAttribute)sitem.GetCustomAttributes(t, false).FirstOrDefault();
                //        if (callModel.Equals(a.Name))
                //        {

                //        }
                //    }
                //}


                //AppInfoAttribute
            }

            public async void SocketReset()
            {
                map.Clear();
                trans.Dispose();
                await InitSocket();                
            }
        }



        public void Dispose()
        {
            rpcPool.Release();
        }

        public class CallClientInfo
        {
            public object Client { get; set; }

            public ConcurrentDictionary<int, Delegate> map = new ConcurrentDictionary<int, Delegate>();
        }

    }
}
